# 缓存

Midscene 支持缓存 Plan 的步骤与匹配到的 DOM 元素信息，减少 AI 模型的调用次数，从而提高执行效率。

**效果**

通过引入缓存后，用例的执行时间大幅降低了，例如从39秒降低到了13秒。

* **before**

![](/cache/no-cache-time.png)

* **after**

![](/cache/use-cache-time.png)

## 使用方式

想要启用缓存特性，有两个关键点：

1. 设置 `MIDSCENE_CACHE=1` 环境变量
2. 设置 `cacheId` 来指定缓存文件名。在 Playwright 和 Yaml 模式下，`cacheId` 会自动设置为测试文件名，在 Javascript 模式下，需要手动设置 `cacheId`。

### Playwright

在 Playwright 模式下，只需要设置 `MIDSCENE_CACHE=1` 环境变量即可。

`cacheId` 会自动设置为测试文件名。

```diff
- playwright test --config=playwright.config.ts
+ MIDSCENE_CACHE=1 playwright test --config=playwright.config.ts
```

### Javascript agent, 例如 PuppeteerAgent, AgentOverChromeBridge

在 Javascript 模式下，需要设置 `MIDSCENE_CACHE=1` 环境变量，并且需要手动设置 `cacheId`。

```diff
- tsx demo.ts 
+ MIDSCENE_CACHE=1 tsx demo.ts
```

```javascript
const mid = new PuppeteerAgent(originPage, {
  cacheId: 'puppeteer-swag-sab', // 增加缓存标识
});
```

### Yaml

在 Yaml 模式下，需要设置 `MIDSCENE_CACHE=1` 环境变量。

`cacheId` 会自动设置为 yaml 文件名。

```diff
- npx midscene ./bing-search.yaml
+ # 增加缓存标识, cacheId 为 yaml 文件名
+ MIDSCENE_CACHE=1 npx midscene ./bing-search.yaml
```

## 缓存策略

### 缓存内容

在 Midscene 中，缓存的内容主要有两类：

1. AI 对于任务的规划（Planning, 即 ai 和 aiAction 方法的结果）
2. AI 对于元素的识别结果

Midscene 不会对 `aiQuery` 和 `aiAssert` 的内容进行缓存，因此可以通过 它们来验证前面 AI 的任务是否符合预期。

### 缓存命中的条件

缓存命中需要同时满足以下条件：

1. 相同的 `cacheId`
2. midscene 版本的 major 和 minor 版本号相同
3. 相同的页面 URL 和页面宽高

当使用缓存进行元素定位时，还需要满足以下条件：

1. 页面中存在与缓存文件中描述的位置和大小均一致的元素
2. 如果使用 VL 模型，则页面中必须有 DOM 元素与缓存文件中描述的坐标相对应。否则，你会在报告中看到 "POSITION NODE" 的元素信息，这些元素并不会被缓存。

### 未命中缓存时，会发生什么？

如果缓存未命中，Midscene 将会重新调用 AI 模型，并更新缓存文件。

## 常见问题

### 为什么在 CI 中始终无法命中？

你需要在 CI 中将缓存文件提交到仓库中，并再次检查缓存命中的条件。

### 如果有了缓存，是否就不需要 AI 服务了？

不是的。缓存不是用于确保脚本长期稳定执行的工具。我们注意到，当页面发生变化时，缓存可能会失效（例如当元素位置略有变化或 DOM 结构发生变化时）。在缓存失效时，我们仍然需要调用 AI 服务来重新执行任务。

### 如何手动删除缓存？

你可以删除缓存文件，或者编辑缓存文件的内容。
